-module(storage).

-include("definitions.hrl").

-export([
  start/0,
  stop/0,
  get_next_id/0,
  get_all_test_ids/0,
  get_test/1,
  add_test/1,
  insert_samples/0,
  get_state/1,
  get_last_state_for_device/1,
  update_state/1,
  get_samples/0,
  get_last_state_for_devices/1]).

-spec start/0 :: () -> ok.
start() ->
  spawn(id_manager, start, []),
  Module = get_module(),
  apply(Module, start, [self()]),
  receive
    {ok, storage_started} ->
      ok
  end.

-spec stop/0 :: () -> ok.
stop() ->
  Module = get_module(),
  ok = apply(Module, stop, []),
  id_manager:stop().

-spec get_next_id/0 :: () -> pos_integer().
get_next_id() ->
  id_manager:get_next_id().

-spec get_module/0 :: () -> module().
get_module() ->
  {ok, DbType} = application:get_env(db_type),
  Module = case DbType of
             mnesia -> mnesia_storage;
             mssql -> sql_storage;
             couch -> couch_storage
           end,
  Module.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% тесты
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec get_all_test_ids/0 :: () -> list(test_id()).
get_all_test_ids() ->
  Module = get_module(),
  apply(Module, get_all_test_ids, []).

-spec get_test/1 :: (integer()) -> test().
get_test(TestId) ->
  Module = get_module(),
  apply(Module, get_test, [TestId]).

-spec add_test/1 :: (test()) -> test_id().
add_test(Test) ->
  Module = get_module(),
  apply(Module, add_test, [Test]).

-spec insert_samples/0 :: () -> ok.
insert_samples() ->
  Module = get_module(),
  ok = apply(Module, insert_samples, []).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% состояния
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec get_state/1 :: (state_id()) -> state().
get_state(StateId) ->
  Module = get_module(),
  apply(Module, get_state, [StateId]).

-spec get_last_state_for_device/1 :: (device_id()) -> state().
get_last_state_for_device(DeviceId) ->
  Module = get_module(),
  apply(Module, get_last_state_for_device, [DeviceId]).

-spec get_last_state_for_devices/1 :: (list(device_id())) -> list(state()).
get_last_state_for_devices(DeviceIdList) ->
  Module = get_module(),
  apply(Module, get_last_state_for_devices, [DeviceIdList]).

-spec update_state/1 :: (state()) -> no_return().
update_state(State) ->
  Module = get_module(),
  apply(Module, update_state, [State]).

-spec get_samples/0 :: () -> [test()].
get_samples() ->
  %%fh,  deviceCode,  operation,  data,  fk,  crc
  % 2, 8, 12, 32, 2, 8
  Message = <<3:2, 0:8, 1:12, 1:32, 3:2, 2:8>>,
  TestData = lists:duplicate(?DEFAULT_TEST_LENGTH, Message),
  DeviceId = 1,
  Samples =
    [
      #testCase{description = "d1", dataField = TestData, desiredAnswer = TestData, deviceId = DeviceId, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d2", dataField = TestData, desiredAnswer = TestData, deviceId = DeviceId + 1, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d3", dataField = TestData, desiredAnswer = TestData, deviceId = 3, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d4", dataField = TestData, desiredAnswer = TestData, deviceId = 4, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d5", dataField = TestData, desiredAnswer = TestData, deviceId = 5, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d6", dataField = TestData, desiredAnswer = TestData, deviceId = 6, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d7", dataField = TestData, desiredAnswer = TestData, deviceId = 7, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d8", dataField = TestData, desiredAnswer = TestData, deviceId = 8, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d9", dataField = TestData, desiredAnswer = TestData, deviceId = 9, dataFieldLen = ?DEFAULT_TEST_LENGTH},
      #testCase{description = "d10", dataField = TestData, desiredAnswer = TestData, deviceId = 10, dataFieldLen = ?DEFAULT_TEST_LENGTH}
    ],
  Samples.